/*
 * PGridView.java
 * Renders a PGrid in a Graphics environment
 */

package sim;

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class PGridView extends JPanel 
                       implements MouseListener {
	
	private PGrid _grid;
	private int _selected;
	private int _nScale;
        private int _nCryptSize;
        private int _xoffset;
        private int _yoffset;
    private Scheduler _scheduler;
	
    public PGridView (PGrid grid, Scheduler scheduler) {
		addMouseListener(this);
		setBackground(Color.black);
		_grid = grid;
		_scheduler = scheduler;
		_selected = 0;
	}
	
	public void paintComponent(Graphics g) {

		// jte -- this greatly improves the image quality
		((Graphics2D)g).setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );

		setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		super.paintComponent(g);
		FontMetrics fm = g.getFontMetrics();
		Dimension d = getSize();
		_nScale = (int)(d.getHeight()/(_grid.getMaxY()+2));
		int temp = (int)(d.getWidth()/(_grid.getMaxX()));
		if (temp<_nScale)
			_nScale = temp;
		_nCryptSize = (int)(_nScale/1.3);
		_xoffset = _nCryptSize;
		_yoffset = _nCryptSize;
                //                ArrayList<Integer> neighbors = _grid.getNeighbors(_selected);
		for (int i=0; i<_grid.getSize(); i++) {
			Crypt crypt = _grid.getCrypt(i);
			if (crypt!=null) {
				double x = crypt.getX();
				double y = crypt.getY();
				//g.setColor(_grid.getCrypt(i).getColor());
				g.fillOval(_xoffset + (int)(x*_nScale),_yoffset + (int)(y*_nScale),
						_nCryptSize,_nCryptSize);				 
			}
		}
		Map ma = new TreeMap();
		
		//ArrayList<Integer> clones = new ArrayList();
		//clones.clear();
		// Draw clone legend to the right of the crypt
		int maxx = (int)_grid.getMaxX();
		/*
		for (int i=0; i<_grid.getSize(); i++) {
		    Crypt crypt = _grid.getCrypt(i);
		    if (crypt!=null) {
			if(_grid.getCrypt(i).getCloneId()==-1){continue;}
			if(!clones.contains((Integer)(_grid.getCrypt(i).getCloneId()))){
			    clones.add(new Integer(_grid.getCrypt(i).getCloneId()));    
			    
			    //g.setColor(_grid.getCrypt(i).getColor());
			    //g.fillOval((int)(maxx*_nScale)+2*_xoffset,3*_yoffset + (int)(clones.size()*_nScale),_nCryptSize,_nCryptSize);
			    // Print clone_id of clone, survival, repro, mutation
			    //g.setColor(new Color(255,255,255));
			    //NumberFormat nFormatter = new DecimalFormat("#00.0");			    
			    ma.put(new Double(_grid.getCloneFrequency(_grid.getCrypt(i).getCloneId())*100.0),new Integer(i));
 
			    //				   new String("Clone "+_grid.getCrypt(i).getCloneId()+
			    //	      "fr="+nFormatter.format(_grid.getCloneFrequency(_grid.getCrypt(i).getCloneId())*100.0)+"% s="+
			    //	      _grid.getCrypt(i).getSurvival()+","+_grid.getCrypt(i).getReproduction()+","+_grid.getCrypt(i).getMutation()));			    
			    //g.drawString("Clone "+_grid.getCrypt(i).getCloneId(),(int)(maxx*_nScale)+4*_xoffset,4*_yoffset + (int)(clones.size()*_nScale));
			    //g.drawString("fr="+
			    //	 nFormatter.format(_grid.getCloneFrequency(_grid.getCrypt(i).getCloneId())*100.0)+"% s="+
			    //	 _grid.getCrypt(i).getSurvival()+","+
			    //	 _grid.getCrypt(i).getReproduction()+","+
			    //	 _grid.getCrypt(i).getMutation(),(int)(maxx*_nScale)+14*_xoffset,4*_yoffset + (int)(clones.size()*_nScale));
			}   
		    }
		}

		*/
		for (Iterator i = _grid._cloneFrequency.keySet().iterator(); i.hasNext();) {
		    Integer key = (Integer)i.next();
		    Double freq = _grid._cloneFrequency.get(key).doubleValue();
		    // If 2 clones have the same frequency, add a slight factor so that both will show up in hash
		    while(ma.containsKey(freq)){
			freq = freq+0.0000000001;
		    }
		    ma.put(new Double(freq),new Integer(key));
		    //System.out.println("cloneid "+key+" freq "+freq);
		}
		// Sort hashtable.
		ArrayList v = new ArrayList(ma.keySet());
		Collections.sort(v);
    
		// Display (sorted) hashtable.
		int y=0;
		for (int it=v.size()-1;it>=0;it--) {
		    Double key = (Double)v.get(it);
		    int i = ((Integer)ma.get(key)).intValue();
		    y+=1;
		    NumberFormat nFormatter = new DecimalFormat("#00.0");
		    //if(_grid.getCrypt(i)!=null){
		    //g.setColor(_scheduler.getCloneColor(i));
			g.fillOval((int)(maxx*_nScale)+2*_xoffset,3*_yoffset + (int)(y*_nScale),_nCryptSize,_nCryptSize);
			g.setColor(new Color(255,255,255));
			g.drawString("Clone "+i,(int)(maxx*_nScale)+4*_xoffset,4*_yoffset + (int)(y*_nScale));
			//g.drawString("fr="+
			//     nFormatter.format(_grid.getCloneFrequency(i)*100.0)+"% s="+
			//     _scheduler.getSurvival(i)+","+
			//     _scheduler.getReproduction(i)+","+
			//     _scheduler.getMutation(i),(int)(maxx*_nScale)+14*_xoffset,4*_yoffset + (int)(y*_nScale));		    
			//}			
		}
		//Iterator it = ma.keySet().iterator();
		//Object obj;
		/*
		int y=0;
		for (Iterator it = ma.keySet().iterator(); it.hasNext();) {
		    y+=1;		    
		    Double key = (Double)it.next();
		    //System.out.println("cloneidaaaa "+key);
		    int i  = ((Integer)ma.get(key)).intValue();
		    NumberFormat nFormatter = new DecimalFormat("#00.0");
		    //if(_grid.getCrypt(i)!=null){
			g.setColor(_scheduler.getCloneColor(i));
			g.fillOval((int)(maxx*_nScale)+2*_xoffset,3*_yoffset + (int)(y*_nScale),_nCryptSize,_nCryptSize);
			g.setColor(new Color(255,255,255));
			g.drawString("Clone "+i,(int)(maxx*_nScale)+4*_xoffset,4*_yoffset + (int)(y*_nScale));
			g.drawString("fr="+
				     nFormatter.format(_grid.getCloneFrequency(i)*100.0)+"% s="+
				     _scheduler.getSurvival(i)+","+
				     _scheduler.getReproduction(i)+","+
				     _scheduler.getMutation(i),(int)(maxx*_nScale)+14*_xoffset,4*_yoffset + (int)(y*_nScale));		    
			//}
			}
		*/
		
		// jte -- disabled crypt info display
/*
		Crypt selected = _grid.getCrypt(_selected);
		if (selected!=null) {
			g.setColor(selected.getColor());
			g.drawString(selected.getInfo(),0,((int)_grid.getMaxY()+1)*_nScale+10);
		}
*/
	}
	public void update() {repaint();}
	public void mouseClicked(MouseEvent e) {
		int mousex = e.getX();
		int mousey = e.getY();
		double closestdist = 100000.0;
		int closest = -1;
		for (int i=0; i<_grid.getSize(); i++) {
			Crypt crypt = _grid.getCrypt(i);
			if (crypt!=null) {
				double x = crypt.getX();
				double y = crypt.getY();

				double dist = (_xoffset+(int)(x*_nScale)+_nCryptSize/2-mousex)*(_xoffset+(int)(x*_nScale)+_nCryptSize/2-mousex) + 
                                  (_yoffset+(int)(y*_nScale)+_nCryptSize/2-mousey)*(_yoffset+(int)(y*_nScale)+_nCryptSize/2-mousey);
				if (dist<closestdist) {
					closestdist = dist;
					closest = i;
				}
			}
		}
		_selected = closest;
		repaint();
	}
	public void mousePressed(MouseEvent e) {
	}
	public void mouseReleased(MouseEvent e) {
	}
	public void mouseEntered(MouseEvent e) {
	}
	public void mouseExited(MouseEvent e) {
	}
}
